package api

import (
	"fmt"
	"log"
	"net/http"
	"strconv"

	"internal-net-bridge-server/internal/config"
	"internal-net-bridge-server/internal/middleware"
	"internal-net-bridge-server/internal/models"
	"internal-net-bridge-server/internal/services"
	"internal-net-bridge-server/internal/tunnel"

	"github.com/gin-gonic/gin"
)

// APIHandler API处理器
type APIHandler struct {
	tunnelManager *tunnel.TunnelManager
	tunnelService *services.TunnelService
}

// NewAPIHandler 创建新的API处理器
// 🔥 关键修复：接收已配置好的 tunnelService（包含 DNSPod 服务）
func NewAPIHandler(tm *tunnel.TunnelManager, ts *services.TunnelService) *APIHandler {
	return &APIHandler{
		tunnelManager: tm,
		tunnelService: ts, // 🔥 使用传入的实例，而不是创建新实例
	}
}

// SetupRoutes 设置路由 (已废弃，路由现在在main.go中统一管理)
// 保留此方法以保持向后兼容性，但不再使用
func (h *APIHandler) SetupRoutes(r *gin.Engine) {
	// 路由现在在main.go中统一设置，包含认证中间件
	// 此方法已废弃，请勿使用
	log.Println("⚠️  SetupRoutes方法已废弃，路由在main.go中统一管理")
}

// CreateTunnel 创建隧道
func (h *APIHandler) CreateTunnel(c *gin.Context) {
	// 统一从认证中间件获取用户ID
	// 如果认证被禁用，中间件会设置默认用户ID
	userID, exists := middleware.GetCurrentUserID(c)
	if !exists {
		models.SendError(c, 401, "用户未认证", nil)
		return
	}

	var req models.TunnelRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		models.SendBadRequest(c, "无效的请求参数", err.Error())
		return
	}

	// 验证请求参数
	if req.LocalPort == "" || req.LocalHost == "" || req.ServerName == "" {
		models.SendBadRequest(c, "localPort、localHost和serverName都是必需的", nil)
		return
	}

	// 🔑 设置UserID（优先使用请求中的UserID，如果没有则使用认证用户ID）
	if req.UserID == "" {
		req.UserID = fmt.Sprintf("%d", userID)
	}
	log.Printf("🔑 [CreateTunnel] UserID=%s (来自认证: %d)", req.UserID, userID)

	// 创建隧道
	response, err := h.tunnelManager.CreateTunnel(&req)
	if err != nil {
		models.SendInternalServerError(c, "创建隧道失败", err.Error())
		return
	}

	// 根据配置决定是否持久化到数据库
	if config.IsPersistenceEnabled() {
		// 🔥 修复：获取数据库中的真实TunnelID
		dbTunnelID, err := h.persistTunnelToDatabase(userID, &req, response)
		if err != nil {
			// 记录错误但不影响隧道创建结果
			log.Printf("⚠️ 隧道持久化到数据库失败: %v", err)
		} else if dbTunnelID != "" && dbTunnelID != response.TunnelID {
			// 🔥 数据库ID与内存ID不同，需要同步
			log.Printf("🔄 检测到TunnelID不一致: 内存ID=%s, 数据库ID=%s", response.TunnelID, dbTunnelID)

			// 🔥 关键修复：同步TunnelManager中的Tunnel对象和监听器
			if err := h.tunnelManager.SyncTunnelID(response.TunnelID, dbTunnelID); err != nil {
				log.Printf("❌ 同步TunnelID失败: %v", err)
			} else {
				log.Printf("✅ TunnelID同步成功: %s -> %s", response.TunnelID, dbTunnelID)
				// 更新响应中的TunnelID
				response.TunnelID = dbTunnelID
			}
		}
	} else {
		log.Printf("💾 隧道持久化已禁用，跳过数据库保存")
	}

	models.SendSuccessWithMessage(c, "隧道创建成功", response)
}

// ListTunnels 列出所有隧道
func (h *APIHandler) ListTunnels(c *gin.Context) {
	// 获取当前用户ID
	userID, exists := middleware.GetCurrentUserID(c)
	if !exists {
		models.SendError(c, 401, "用户未认证", nil)
		return
	}

	// 获取内存中的隧道信息（实时连接状态）
	memoryTunnels := h.tunnelManager.ListTunnels()

	// 创建内存隧道的映射，方便查找
	memoryTunnelMap := make(map[string]*models.Tunnel)
	for _, tunnel := range memoryTunnels {
		memoryTunnelMap[tunnel.ID] = tunnel
	}

	// 获取数据库中的隧道映射信息（包含 public_url 和 tunnel_type）
	var responses []gin.H

	if config.IsPersistenceEnabled() {
		// 如果启用了持久化，从数据库获取完整信息
		dbTunnels, err := h.tunnelService.GetAllTunnelMappingsByUserID(userID)
		if err != nil {
			log.Printf("❌ 获取数据库隧道映射失败: %v", err)
			// 降级到仅返回内存中的隧道（按创建时间倒序）
			for i := len(memoryTunnels) - 1; i >= 0; i-- {
				tunnel := memoryTunnels[i]
				// 🔥 根据isConnected状态设置status字段，确保客户端自动重连功能正常
				status := "inactive"
				if tunnel.IsConnected {
					status = "active"
				}
				responses = append(responses, gin.H{
					"tunnelId":    tunnel.ID,
					"localHost":   tunnel.LocalHost,
					"localPort":   tunnel.LocalPort,
					"serverName":  tunnel.ServerName,
					"tunnelHost":  tunnel.TunnelHost,
					"tunnelPort":  tunnel.TunnelPort,
					"publicPort":  tunnel.PublicPort,
					"isConnected": tunnel.IsConnected,
					"status":      status, // 🔥 添加status字段
					"createdAt":   tunnel.CreatedAt,
					"public_url":  nil,
					"tunnel_type": "http", // 默认类型
				})
			}
		} else {
			// 合并数据库信息和内存状态
			for _, dbTunnel := range dbTunnels.Tunnels {
				memoryTunnel := memoryTunnelMap[dbTunnel.TunnelID]

				response := gin.H{
					"tunnelId":    dbTunnel.TunnelID,
					"localHost":   dbTunnel.LocalIP,
					"localPort":   dbTunnel.LocalPort,
					"serverName":  dbTunnel.ServiceName,
					"publicPort":  dbTunnel.PublicPort,
					"public_url":  dbTunnel.PublicURL,
					"tunnel_type": dbTunnel.TunnelType,
					"status":      dbTunnel.Status,
					"createdAt":   dbTunnel.CreatedAt,
				}

				// 如果内存中有对应的隧道，添加实时状态信息
				if memoryTunnel != nil {
					response["tunnelHost"] = memoryTunnel.TunnelHost
					response["tunnelPort"] = memoryTunnel.TunnelPort
					response["isConnected"] = memoryTunnel.IsConnected
				} else {
					// 内存中没有，说明隧道未连接
					response["tunnelHost"] = ""
					response["tunnelPort"] = ""
					response["isConnected"] = false
				}

				responses = append(responses, response)
			}
		}
	} else {
		// 未启用持久化，仅返回内存中的隧道（按创建时间倒序）
		for i := len(memoryTunnels) - 1; i >= 0; i-- {
			tunnel := memoryTunnels[i]
			// 🔥 根据isConnected状态设置status字段，确保客户端自动重连功能正常
			status := "inactive"
			if tunnel.IsConnected {
				status = "active"
			}
			responses = append(responses, gin.H{
				"tunnelId":    tunnel.ID,
				"localHost":   tunnel.LocalHost,
				"localPort":   tunnel.LocalPort,
				"serverName":  tunnel.ServerName,
				"tunnelHost":  tunnel.TunnelHost,
				"tunnelPort":  tunnel.TunnelPort,
				"publicPort":  tunnel.PublicPort,
				"isConnected": tunnel.IsConnected,
				"status":      status, // 🔥 添加status字段
				"createdAt":   tunnel.CreatedAt,
				"public_url":  nil,
				"tunnel_type": "http", // 默认类型
			})
		}
	}

	data := gin.H{
		"tunnels": responses,
		"count":   len(responses),
	}
	models.SendSuccess(c, data)
}

// GetTunnel 获取单个隧道信息
func (h *APIHandler) GetTunnel(c *gin.Context) {
	tunnelID := c.Param("id")

	tunnel, exists := h.tunnelManager.GetTunnel(tunnelID)
	if !exists {
		models.SendNotFound(c, "隧道不存在")
		return
	}

	data := gin.H{
		"tunnelId":    tunnel.ID,
		"localHost":   tunnel.LocalHost,
		"localPort":   tunnel.LocalPort,
		"serverName":  tunnel.ServerName,
		"tunnelHost":  tunnel.TunnelHost,
		"tunnelPort":  tunnel.TunnelPort,
		"publicPort":  tunnel.PublicPort,
		"isConnected": tunnel.IsConnected,
		"createdAt":   tunnel.CreatedAt,
	}
	models.SendSuccess(c, data)
}

// UpdateTunnel 更新隧道
func (h *APIHandler) UpdateTunnel(c *gin.Context) {
	tunnelID := c.Param("id")
	if tunnelID == "" {
		models.SendError(c, http.StatusBadRequest, "隧道ID不能为空", nil)
		return
	}

	userID, exists := c.Get("user_id")
	if !exists {
		models.SendError(c, http.StatusUnauthorized, "用户未认证", nil)
		return
	}

	uid, ok := userID.(uint)
	if !ok {
		models.SendError(c, http.StatusInternalServerError, "用户ID类型错误", nil)
		return
	}

	var req models.TunnelRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		models.SendError(c, http.StatusBadRequest, "请求参数错误: "+err.Error(), nil)
		return
	}

	// 调试日志
	log.Printf("🔧 UpdateTunnel请求参数: LocalHost=%s, LocalPort=%s, ServerName=%s, TunnelType=%s",
		req.LocalHost, req.LocalPort, req.ServerName, req.TunnelType)

	// 验证隧道类型
	if req.TunnelType != models.TunnelTypeHTTP && req.TunnelType != models.TunnelTypeTCP {
		models.SendError(c, http.StatusBadRequest, "不支持的隧道类型: "+req.TunnelType, nil)
		return
	}

	// 解析本地端口
	localPort, err := strconv.Atoi(req.LocalPort)
	if err != nil || localPort <= 0 || localPort > 65535 {
		models.SendError(c, http.StatusBadRequest, "无效的本地端口", nil)
		return
	}

	// 构建隧道映射更新请求
	mappingReq := &models.TunnelMappingRequest{
		ServiceName:   req.ServerName,
		LocalIP:       req.LocalHost,
		LocalPort:     int64(localPort),
		TunnelType:    req.TunnelType,
		TCPTunnelPort: 0,
	}

	// 更新数据库中的隧道映射
	tunnelMapping, err := h.tunnelService.UpdateTunnelMapping(tunnelID, uid, mappingReq)
	if err != nil {
		models.SendError(c, http.StatusInternalServerError, "更新隧道映射失败: "+err.Error(), nil)
		return
	}

	// 构建响应
	response := &models.TunnelResponse{
		TunnelID:   tunnelMapping.TunnelID,
		TunnelHost: "127.0.0.1", // 隧道服务器地址
		TunnelPort: strconv.FormatInt(tunnelMapping.TCPTunnelPort, 10),
		PublicPort: strconv.FormatInt(tunnelMapping.PublicPort, 10),
	}

	models.SendSuccess(c, response)
}

// DeleteTunnel 删除隧道
func (h *APIHandler) DeleteTunnel(c *gin.Context) {
	tunnelID := c.Param("id")
	if tunnelID == "" {
		models.SendBadRequest(c, "隧道ID不能为空", nil)
		return
	}

	// 获取用户ID
	userID, exists := middleware.GetCurrentUserID(c)
	if !exists {
		models.SendError(c, 401, "用户未认证", nil)
		return
	}

	log.Printf("🗑️  删除隧道请求: TunnelID=%s, UserID=%d", tunnelID, userID)

	// 1. 从内存中删除隧道连接（包括关闭连接和监听器）
	if err := h.tunnelManager.DeleteTunnel(tunnelID); err != nil {
		log.Printf("⚠️  从内存删除隧道失败（可能已不存在）: %v", err)
		// 不影响后续的数据库删除操作
	} else {
		log.Printf("✅ 隧道已从内存删除: %s", tunnelID)
	}

	// 2. 从数据库中删除隧道记录（如果启用了持久化）
	if config.IsPersistenceEnabled() {
		if err := h.tunnelService.DeleteTunnelMapping(tunnelID, userID); err != nil {
			log.Printf("❌ 从数据库删除隧道失败: %v", err)
			models.SendInternalServerError(c, "删除隧道失败", err.Error())
			return
		}
		log.Printf("✅ 隧道已从数据库删除: %s", tunnelID)
	}

	data := gin.H{
		"tunnelId": tunnelID,
	}
	models.SendSuccessWithMessage(c, "隧道已删除", data)
	log.Printf("✅ 隧道删除成功: %s", tunnelID)
}

// persistTunnelToDatabase 将隧道信息持久化到数据库
// 返回值: (数据库中的TunnelID, error)
func (h *APIHandler) persistTunnelToDatabase(userID uint, req *models.TunnelRequest, response *models.TunnelResponse) (string, error) {
	// 转换 TunnelRequest 为 TunnelMappingRequest
	localPort, err := strconv.ParseInt(req.LocalPort, 10, 64)
	if err != nil {
		return "", fmt.Errorf("无效的本地端口: %w", err)
	}

	// 构建隧道映射请求
	mappingReq := &models.TunnelMappingRequest{
		ServiceName:   req.ServerName,
		LocalIP:       req.LocalHost,
		LocalPort:     localPort,
		TunnelType:    req.TunnelType, // 使用请求中的隧道类型
		TCPTunnelPort: 0,
	}

	// 调试日志
	log.Printf("🔧 隧道映射请求参数: UserID=%d, LocalIP=%s, LocalPort=%d, ServiceName=%s, TunnelType=%s",
		userID, mappingReq.LocalIP, mappingReq.LocalPort, mappingReq.ServiceName, mappingReq.TunnelType)

	// 🔥 优化：使用 userID + LocalIP + LocalPort 唯一确定隧道
	existingTunnel, err := h.tunnelService.GetTunnelMappingByUserAndLocalAddress(userID, mappingReq.LocalIP, mappingReq.LocalPort)

	var targetTunnelID string

	if err == nil && existingTunnel != nil {
		// 隧道已存在，更新隧道信息
		log.Printf("📝 发现现有隧道: UserID=%d, LocalIP=%s, LocalPort=%d (TunnelID: %s)",
			userID, mappingReq.LocalIP, mappingReq.LocalPort, existingTunnel.TunnelID)
		log.Printf("   └─ 旧服务名: %s, 新服务名: %s", existingTunnel.ServiceName, req.ServerName)

		// 使用现有的 tunnel_id 更新其他信息（包括服务名）
		_, updateErr := h.tunnelService.UpdateTunnelMapping(existingTunnel.TunnelID, userID, mappingReq)
		if updateErr != nil {
			return "", fmt.Errorf("更新隧道映射失败: %w", updateErr)
		}

		log.Printf("✅ 隧道映射更新成功: %s -> %s (LocalIP=%s, LocalPort=%d)",
			existingTunnel.ServiceName, req.ServerName, mappingReq.LocalIP, mappingReq.LocalPort)
		targetTunnelID = existingTunnel.TunnelID
	} else {
		// 隧道不存在，创建新隧道
		log.Printf("📝 创建新隧道映射: UserID=%d, LocalIP=%s, LocalPort=%d, ServiceName=%s",
			userID, mappingReq.LocalIP, mappingReq.LocalPort, req.ServerName)

		tunnelMapping, createErr := h.tunnelService.CreateTunnelMapping(userID, mappingReq)
		if createErr != nil {
			return "", fmt.Errorf("创建隧道映射失败: %w", createErr)
		}

		log.Printf("✅ 隧道映射创建成功: %s (UserID=%d, LocalIP=%s, LocalPort=%d, 数据库ID=%d)",
			req.ServerName, userID, mappingReq.LocalIP, mappingReq.LocalPort, tunnelMapping.ID)
		targetTunnelID = tunnelMapping.TunnelID
	}

	// 获取隧道映射信息（用于域名注册）
	tunnelMapping, err := h.tunnelService.GetTunnelMappingByID(targetTunnelID)
	if err != nil {
		log.Printf("⚠️  获取隧道映射失败: %v", err)
		return targetTunnelID, nil // 🔥 返回targetTunnelID（即使获取失败也要返回ID）
	}

	// 🔥 优化：启动公共端口监听器或注册域名映射
	if tunnelMapping != nil && tunnelMapping.PublicURL != nil && *tunnelMapping.PublicURL != "" {
		domain, err := h.tunnelService.GetDomainByTunnelID(targetTunnelID)
		if err != nil {
			log.Printf("⚠️  提取域名失败: %v", err)
		}

		// 检查DomainRouter是否启用
		var domainRouterEnabled bool
		if h.tunnelManager != nil {
			domainRouter := h.tunnelManager.GetDomainRouter()
			if domainRouter != nil && domain != "" {
				// DomainRouter已启用，注册域名映射
				publicPortInt := int(tunnelMapping.PublicPort)
				domainRouter.AddMapping(domain, publicPortInt)
				log.Printf("🌐 域名映射已注册: %s -> :%d", domain, publicPortInt)
				domainRouterEnabled = true
			}
		}

		// 🔥 关键优化：如果DomainRouter未启用，启动公共端口监听器
		if !domainRouterEnabled && h.tunnelManager != nil {
			publicPortInt := int(tunnelMapping.PublicPort)
			if err := h.tunnelManager.StartPublicPortListenerForTunnelID(targetTunnelID, int64(publicPortInt)); err != nil {
				log.Printf("❌ 启动公共端口监听器失败: %v", err)
			} else {
				log.Printf("✅ 公共端口监听器已启动（DomainRouter未启用）: :%d -> 隧道 %s", publicPortInt, targetTunnelID)
			}
		}
	}

	// 如果有域名信息，更新public_url（向后兼容）
	if response.Domain != "" && targetTunnelID != "" {
		publicURL := fmt.Sprintf("https://%s", response.Domain)
		if err := h.tunnelService.UpdateTunnelPublicURL(targetTunnelID, publicURL); err != nil {
			log.Printf("❌ 更新隧道public_url失败: %v", err)
		} else {
			log.Printf("✅ 隧道public_url已更新: %s -> %s", targetTunnelID, publicURL)
		}
	}

	// 🔥 返回数据库中的真实TunnelID
	return targetTunnelID, nil
}

// UpdateTunnelConnectionStatus 更新隧道连接状态
// PATCH /api/tunnels/:id/status
func (h *APIHandler) UpdateTunnelConnectionStatus(c *gin.Context) {
	tunnelID := c.Param("id")
	if tunnelID == "" {
		models.SendError(c, http.StatusBadRequest, "隧道ID不能为空", nil)
		return
	}

	userID, exists := c.Get("user_id")
	if !exists {
		models.SendError(c, http.StatusUnauthorized, "用户未认证", nil)
		return
	}

	uid, ok := userID.(uint)
	if !ok {
		models.SendError(c, http.StatusInternalServerError, "用户ID类型错误", nil)
		return
	}

	// 解析请求参数
	var req struct {
		Status       string  `json:"status" binding:"required,oneof=active inactive connecting disconnected error"`
		ErrorMessage *string `json:"error_message,omitempty"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		models.SendError(c, http.StatusBadRequest, "请求参数错误: "+err.Error(), nil)
		return
	}

	log.Printf("🔧 UpdateTunnelConnectionStatus请求: TunnelID=%s, Status=%s, UserID=%d", tunnelID, req.Status, uid)

	// 验证隧道所有权并更新状态
	if err := h.tunnelService.UpdateTunnelStatusByUserID(tunnelID, uid, req.Status, req.ErrorMessage); err != nil {
		log.Printf("❌ 更新隧道状态失败: %v", err)
		models.SendError(c, http.StatusInternalServerError, "更新隧道状态失败: "+err.Error(), nil)
		return
	}

	log.Printf("✅ 隧道状态更新成功: %s -> %s", tunnelID, req.Status)
	models.SendSuccessWithMessage(c, "隧道状态更新成功", gin.H{
		"tunnel_id": tunnelID,
		"status":    req.Status,
	})
}
